Set-StrictMode -Version 2.0
$ErrorActionPreference="Stop"

function Export-Certificate($certificate, $filePath, $privateKeyPassword)
{
    $exportType = [System.IO.Path]::GetExtension($filePath)
    if ((".cer",".cert") -contains $exportType)
    {
        $bytes = $certificate.Export("cert")
    }
    elseif ((".pfx",".p12" -contains $exportType))
    {
        if ($privateKeyPassword -eq $null)
        {
            $bytes = $certificate.Export("pfx")
        }
        else
        {
            $bytes = $certificate.Export("pfx",$privateKeyPassword)
        }
    }
    else
    {
        throw "$exportType is an unknown file extension - only cer and pfx are supported"
    }

    # Todo Implement -force
    # WriteAllBytes will overwrite a file so try new-item first if new-item fails, the fail already exists and we don't want to continue.
    $newFile = new-item $filePath -type file
    if ($newFile -eq $null)
    {
        throw 
    }
    $filePath = split-path $newFile -noqualifier
    [System.IO.File]::WriteAllBytes($filePath,$bytes)
}

function global:Copy-Certificate(
          [parameter(mandatory=$true)]
          [String]
        $source, 
          [parameter(mandatory=$true)]
          [String]
        $destination, 
        $password,
      [Switch]
      $NotExportable
        )
{
<#
.Description
    Copy-Ceritificate allows import export and copying of certificates.

    To detemine the type the type of cert you want to export,  Copy-Certificate looks at the file exension.

    Export a certificate as a .cer file (no private key exported, and no password)
        Copy-Certificate EDB3A1BCA189DD29F4D0700B5839FC119D0D37D3 c:\temp\foo.cer

    Export a certificate as a pfx file (will export private key if it exists)
        Copy-Certificate EDB3A1BCA189DD29F4D0700B5839FC119D0D37D3 c:\temp\foo.pfx -password donkey

    Import a certificate with privatekey to a store
        Copy-Certificate c:\temp\foo.pfx cert:\LocalMachine\My -password myPassword.

    Import a certificate without privatekey to a store
        Copy-Certificate c:\temp\foo.cer cert:\LocalMachine\Root 

    Copy a certificate to another certificate store.
        Copy-Certificate EDB3A1BCA189DD29F4D0700B5839FC119D0D37D3 cert:\LocalMachine\Root

#>
	function ToCertObject($object)
	{
        $CertObjectTypes = @(
            [System.Security.Cryptography.X509Certificates.X509Certificate2],
            [Microsoft.Powershell.Commands.X509StoreLocation]
            )
        if  ($CertObjectTypes -Contains $object.GetType())
        {
            return $obj
        }
        # Objet must be a path
        $pathOfObject = $object
        get-item $pathOfObject
	}
    #$source = ToCertObject $source
    #$destination = ToCertObject $destination

    $myDest="junk"
    if (test-path $destination)
    {
        $myDest = gi $destination
    }
        
    if ($myDest -is  [System.Security.Cryptography.X509Certificates.X509Store])
    {
        $mySrc = gi $source
        if ($mySrc -is  [System.IO.FileSystemInfo])
        {
            # Import Cert case
            ############################################################################
            $filePath = split-path $mySrc -noqualifier
            $bytes = [System.IO.File]::ReadAllBytes($filePath)
        
            #  BTW - Can we merge flags from using a string in powershell?
            $keyStorageFlags  = [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::PersistKeySet 
            if (-not $NotExportable)
            {
                $keyStorageFlags  = $keyStorageFlags -bor [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable
            }

            $importedCert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 ($bytes,$password, $keyStorageFlags)

            $myDest.Open("ReadWrite")
            $myDest.Add($importedCert)
            $myDest.Close()
            return
        }
        if ($mySrc -is [System.Security.Cryptography.X509Certificates.X509Certificate2])
        {
            throw "Copy Certifcate to Another Store not yet implemented"
        }
        else
        {
            throw "Destination is CertificateStore, $source must be a certificate or file (containing the bytes of a certificate)"
        }
    }

    # Assume it's an export then.
    ############################################################################
    Export-Certificate (get-item $source ) $destination $password
}
